package com.tanhua.dubbo.es.api;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.dubbo.config.annotation.Service;
import com.tanhua.dubbo.server.api.UserLocationApi;
import com.tanhua.dubbo.server.pojo.UserLocation;
import com.tanhua.dubbo.server.vo.PageInfo;
import com.tanhua.dubbo.server.vo.UserLocationVo;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.*;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;

@Service(version = "1.0.0")
@Slf4j
public class UserLocationApiImpl implements UserLocationApi {
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    /**
     * 初始化索引库
     *
     */
    @PostConstruct
    public void init(){
        if(!elasticsearchTemplate.indexExists("tanhua"))
        {
            elasticsearchTemplate.createIndex(UserLocation.class);
        }
        if(!elasticsearchTemplate.typeExists("tanhua","user_location"))
            elasticsearchTemplate.putMapping(UserLocation.class);

    }
    @Override
    public Boolean updateUserLocation(Long userId, Double longitude, Double latitude, String address) {
        GetQuery getQuery = new GetQuery();
        getQuery.setId(String.valueOf(userId));
        //查询个人的地理位置数据，如果不存在，需要新增，如果是存在数据，更新数据
        try {
            UserLocation userLocation = elasticsearchTemplate.queryForObject(getQuery, UserLocation.class);
            if(ObjectUtil.isEmpty(userLocation))

            {
                userLocation = new UserLocation();
                userLocation.setUserId(userId);
                userLocation.setAddress(address);
                userLocation.setLastUpdated(System.currentTimeMillis());
                userLocation.setCreated(System.currentTimeMillis());
                userLocation.setUpdated(System.currentTimeMillis());
                userLocation.setLocation(new GeoPoint(latitude,longitude));
                IndexQuery indexQuery = new IndexQuery();
                indexQuery.setObject(userLocation);
                //保存数据到ES中
                elasticsearchTemplate.index(indexQuery);
            }else
            {
                //更新数据
                Map<String,Object>map=new HashMap<>();
                map.put("location", new GeoPoint(latitude, longitude));
                map.put("updated", System.currentTimeMillis());
                map.put("lastUpdated", userLocation.getUpdated());
                map.put("address", address);
                UpdateRequest updateRequest = new UpdateRequest();
                updateRequest.doc(map);
                UpdateQuery build = new UpdateQueryBuilder()
                        .withId(String.valueOf(userId))
                        .withClass(UserLocation.class)
                        .withUpdateRequest(updateRequest).build();
                //更新数据
                 elasticsearchTemplate.update(build);


            }
            return true;
        } catch (Exception e) {
            log.error("更新地理位置失败~ userId = " + userId +
                    ", longitude = " + longitude + ", latitude = " +
                    latitude + ", address = " + address, e);
        }
        return false;

    }
    /**
     * 查询用户的位置信息
     *
     * @param userId
     * @return
     */
    @Override
    public UserLocationVo queryByUserId(Long userId) {
        GetQuery getQuery = new GetQuery();
        getQuery.setId(String.valueOf(userId));
        UserLocation userLocation = elasticsearchTemplate.queryForObject(getQuery, UserLocation.class);
        if(ObjectUtil.isNotEmpty(userLocation))
        return UserLocationVo.format(userLocation);
        return null;
    }



    @Override
    public PageInfo<UserLocationVo> queryUserFromLocation(Double longitude, Double latitude, Double distance, Integer page, Integer pageSize) {
        PageInfo<UserLocationVo> userLocationVoPageInfo = new PageInfo<>();
        userLocationVoPageInfo.setPageSize(pageSize);
        userLocationVoPageInfo.setPageSize(page);
        String fieldName = "location";
        NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
        PageRequest pageRequest = PageRequest.of(page - 1, pageSize);
        searchQueryBuilder.withPageable(pageRequest);
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        //以一个点为中心，指定范围查询
        GeoDistanceQueryBuilder DistanceQueryBuilder = new GeoDistanceQueryBuilder(fieldName);
        //中心点
        DistanceQueryBuilder.point(new GeoPoint(latitude,longitude));
        //距离（画圆的半径）单位：公里
        DistanceQueryBuilder.distance(distance/1000, DistanceUnit.KILOMETERS);
        boolQueryBuilder.must(DistanceQueryBuilder);
        searchQueryBuilder.withQuery(boolQueryBuilder);
        GeoDistanceSortBuilder geoDistanceSortBuilder = new GeoDistanceSortBuilder(fieldName, latitude, longitude);
        geoDistanceSortBuilder.order(SortOrder.ASC);
        geoDistanceSortBuilder.unit(DistanceUnit.KILOMETERS);
        searchQueryBuilder.withSort(geoDistanceSortBuilder);
        AggregatedPage<UserLocation> userLocations = elasticsearchTemplate.queryForPage(searchQueryBuilder.build(), UserLocation.class);
        if(CollUtil.isEmpty(userLocations.getContent()))
            return userLocationVoPageInfo;
        userLocationVoPageInfo.setRecords(UserLocationVo.formatToList(userLocations.getContent()));
        return userLocationVoPageInfo;
    }
}
